<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es5 对象判断方法</title>
  <!-- 
  在 JavaScript ES5 中，判断对象的类型和属性是一个常见的需求。
  1. 判断对象类型
  在 JavaScript 中，可以使用 typeof 和 instanceof 运算符来判断对象的类型。

   1.1 使用 typeof
  typeof 运算符可以用来判断变量的基本类型，但对于对象，它返回的是 "object"。因此，使用 typeof 判断对象时需要谨慎。
  var obj = {};
  console.log(typeof obj); // 输出: "object"

  var arr = [];
  console.log(typeof arr); // 输出: "object" （数组也是对象）

  var func = function() {};
  console.log(typeof func); // 输出: "function" （函数也是对象）
   1.2 使用 instanceof
 instanceof 运算符可以用来判断一个对象是否是某个构造函数的实例。
  var obj = {};
  console.log(obj instanceof Object); // 输出: true

  var arr = [];
  console.log(arr instanceof Array); // 输出: true
  console.log(arr instanceof Object); // 输出: true

  var date = new Date();
  console.log(date instanceof Date); // 输出: true
  2. 判断对象属性
  在 JavaScript 中，可以使用 hasOwnProperty() 方法和 in 运算符来判断对象是否具有某个属性。

   2.1 使用 hasOwnProperty()
  hasOwnProperty() 方法用于判断对象自身是否具有指定的属性，而不检查原型链。
  var obj = {
      name: "Alice"
  };

  console.log(obj.hasOwnProperty("name")); // 输出: true
  console.log(obj.hasOwnProperty("age"));  // 输出: false
   2.2 使用 in 运算符
 in 运算符用于判断对象是否具有指定的属性，包括原型链上的属性。
  var obj = {
      name: "Alice"
  };

  console.log("name" in obj); // 输出: true
  console.log("age" in obj);  // 输出: false

  // 继承属性
  Object.prototype.age = 25;
  console.log("age" in obj);  // 输出: true
  3. 总结
  在 ES5 中，判断对象的方法主要包括使用 typeof 和 instanceof 来判断对象类型，使用 hasOwnProperty() 和 in 运算符来判断对象属性。这些方法在处理对象时非常有用，能够帮助开发者更好地理解和管理对象的结构和属性。理解这些判断方法对于编写高效和可维护的 JavaScript 代码至关重要。
   -->
</head>
<body>

  <script>
    // 创建对象过程
    function createObject(o) {
      function F() {}
      F.prototype = o;
      return new F();
    }

    // 将Subtype和Supertype联系在一起
    // 寄生式函数
    function inheritPrototype(Subtype, Supertype) {
      // Subtype.prototype.__proto__ = Supertype.prototype
      // Object.setPrototypeOf(Subtype.prototype, Subtype.prototype)
      Subtype.prototype = createObject(Supertype.prototype);
      Object.defineProperty(Subtype.prototype, 'constructor', {
        enumerable: false,
        configurable: true,
        writable: true,
        value: Subtype
      })
      Object.setPrototypeOf(Subtype, Supertype);
      // Subtype.__proto__ = Supertype
    }
  </script>
  <script>
    const obj = {
      name: '张三',
      age: 18
    }

    // 1. typeof
    console.log(typeof obj);  // 输出: object
    // 2. instanceof
    console.log(obj instanceof Object);  // 输出: true
    // 3. hasOwnProperty()
    console.log(obj.hasOwnProperty('name'));  // 输出: true
    // 4. in 运算符
    console.log('name' in obj);  // 输出: true
    console.log('info' in obj);  // 输出: false
    // 5. Object.prototype.toString.call()
    console.log(Object.prototype.toString.call(obj));  // 输出: [object Object]
    // 6. Object.getPrototypeOf()
    console.log(Object.getPrototypeOf(obj));  // 输出: [object Object]
    // 7. Object.keys()
    console.log(Object.keys(obj));  // 输出: ['name', 'age']
    // 8. Object.values()
    console.log(Object.values(obj));  // 输出: ['张三', 18]
    // 9. Object.entries()
    console.log(Object.entries(obj));  // 输出: [['name', '张三'], ['age', 18]]
    // 10. Object.getOwnPropertyNames()
    console.log(Object.getOwnPropertyNames(obj));  // 输出: ['name', 'age']
    // 11. Object.getOwnPropertySymbols()
    console.log(Object.getOwnPropertySymbols(obj));  // 输出: []
    // 12. Object.is()
    console.log(Object.is(obj, obj));  // 输出: true
    // 13. Object.isExtensible()
    console.log(Object.isExtensible(obj));  // 输出: true
    // 14. Object.isFrozen()
    console.log(Object.isFrozen(obj));  // 输出: false
    // 15. Object.isSealed()
    console.log(Object.isSealed(obj));  // 输出: false
    // 16. Object.preventExtensions()
    console.log(Object.preventExtensions(obj));  // 输出: [object Object]
    // 17. Object.freeze()
    console.log(Object.freeze(obj));  // 输出: [object Object]
    // 18. Object.seal()
    console.log(Object.seal(obj));  // 输出: [object Object]
    // 19. Object.getOwnPropertyDescriptor()
    console.log(Object.getOwnPropertyDescriptor(obj, 'name'));  // 输出: {value: '张三', writable: true, enumerable: true, configurable: true}
    // 20. Object.getOwnPropertyDescriptors()
    console.log(Object.getOwnPropertyDescriptors(obj));  // 输出: {name: {…}, age: {…}}
    
    var info = createObject(obj)
    info.address = "中国"
    info.intro = "中国大好河山"

    console.log(info.name, info.address)
    console.log(info)
    for (var key in info) {
      console.log(key)
    } // 输出: name age
    // 21.instanceof
    // instanceof用于判断对象和类(构造函数)之间的关系
    function Person() {}
    function Student() {}
    inheritPrototype(Student, Person)

    // stu实例(instance)对象
    var stu = new Student()
    console.log(stu instanceof Student)
    console.log(stu instanceof Person)
    console.log(stu instanceof Object)
    console.log(stu instanceof Array)

    // 4.isPrototypeOf
    console.log(Student.prototype.isPrototypeOf(stu))
    console.log(Person.prototype.isPrototypeOf(stu))
    
    // 可以用于判断对象之间的继承
    console.log(obj.isPrototypeOf(info))
    
  </script>
  
</body>
</html>